module memoryAlloctor (
    input wire clk,
    input wire rst,
    input wire ram_pick,
    input wire write_en,
    input wire [9:0] write_size,
    input wire [5:0] write_priority,
    input wire [15:0] write_port,
    input wire data_en_in,
    input wire [31:0] data_in,
    input wire dequeue_en,
    input wire [9:0] dequeue_value,
    input wire [15:0] enqueue_sucess,
    input wire enqueue_ack,
    output reg enqueue_en,
    output reg [15:0] enqueue_port,
    output reg [5:0] enqueue_priority,
    output reg [9:0] enqueue_value,
    output reg dequeue_success,
    output wire manager_read_ready,
    output reg manager_write_ready,                    //RAM写就绪标�?
    output reg address_ready,                          //地址准备就绪标志
    output reg write_padding_out,                      //写填充使�?                   
    output reg write_en_out,                           //写使�?
    output reg [12:0] write_address_out,               //写地�?
    output reg [31:0] write_data_out,                  //写内�?
    output reg read_en_out,                            //读使�?
    output reg [12:0] read_address_out                 //读地�?
);
    //队列中元素组织指�?
    reg [15:0] block_queue_next [0:255];
    //数据块对应的地址寄存器组
    reg [9:0] block_address [0:255];
    //数据块对应的下一块序号寄存器�?
    reg [9:0] block_next [0:255];
    //当前数据快是否为数据包最后一块的标记寄存器组
    reg block_is_last [0:255];
    //数据包的长度
    reg [9:0] package_size [0:255];
    //读写计数�?
    reg [9:0] read_address_counter, totle_read_counter, history_read_index;
    reg [9:0] write_address_counter;
    //空闲块队�?
    reg [9:0] available_list [0:255];
    //空闲链表指针
    reg [9:0] available_head, available_tail;
    //读状态机
    reg read_state;
    reg [9:0] read_block;
    reg [14:0] read_address;
    //璁需要暂存的寄存�?
    reg [9:0] history_data_size;
    reg [5:0] history_data_priority;
    reg [15:0] history_data_port;
    reg [9:0] history_data_index;
    //写状态机
    reg [1:0] write_state;
    reg [9:0] now_write_size;
    reg [9:0] write_block;
    integer i = 0;

    //读状态转移
    always @(posedge clk) begin
        if (rst) begin
            write_state <= 2'b00;
            write_address_counter <= 0;
            manager_write_ready <= 1;
            //初始化块的地址
            for (i = 0; i < 256; i=i+1) begin          
                block_address[i] <= i*32;
                package_size[i] <= 0;
            end
            write_padding_out <= 0;
            address_ready <= 1'b0;
            available_head <= 0;

            enqueue_en <= 0;
            enqueue_port <= 0;
            enqueue_priority <= 0;
            enqueue_value <= 0;
        end
        else begin
            if (write_state == 2'b00 && write_en) begin
                write_state <= 2'b01;
                address_ready <= 1'b1;
                manager_write_ready <= 0;
                //暂存信息，后面会用到
                history_data_size <= write_size;
                history_data_port <= write_port;
                history_data_priority <= write_priority;
                history_data_index <= available_list[available_head];
                //从空闲队列中取出一块分配给数据包使用
                write_block <= available_list[available_head];
                write_address_counter <= 0;

                //空闲队列指针向后移动并取模，实现循环队列的功能
                if (available_head + 1 < 256) begin
                    available_head <= available_head + 1;
                end
                else begin
                    available_head <= 0;
                end
            end

            if (write_state == 2'b01 && data_en_in) begin
                write_state <= 2'b10;
                write_en_out <= 1'b1;
                write_data_out <= data_in;
                write_address_out <= block_address[write_block] + write_address_counter;
                write_address_counter <= write_address_counter + 1;
                package_size[write_block] <= history_data_size;
            end

            if (write_state == 2'b11) begin
                //需要填充结束，直接终止就可以了
                write_state <= 2'b00;
                address_ready <= 1'b0;
                write_en_out <= 1'b0;
                write_padding_out <= 1'b0;
                manager_write_ready <= 1;
            end

            if (write_state == 2'b10) begin
                write_en_out <= 1'b1;
                write_data_out <= data_in;
                write_address_out <= block_address[write_block] + write_address_counter;
                write_address_counter <= write_address_counter + 1;
                if (write_address_counter >= history_data_size) begin
                    write_padding_out <= 1'b1;
                    //已经开始写多余的内容
                    //记录一下last
                    block_is_last[write_block] <= 1'b1;
                    //切换状态
                    write_state <= 2'b11;
                end
                else begin
                    write_padding_out <= 1'b0;
                end
                //如果已经写满了一个内存块
                if (write_address_counter == 32) begin
                    if (write_block == history_data_index) begin
                        //如果是第一块写完了，发出入队请求
                        enqueue_en <= 1'b1;
                        enqueue_port <= history_data_port;
                        enqueue_priority <= history_data_priority;
                        enqueue_value <= history_data_index;
                    end

                    write_address_counter <= 1;
                    if (history_data_size - 32 < history_data_size) begin //数据已经不足一个完整快
                        //记录一下next和last标记
                        block_is_last[write_block] <= 1'b0;
                        block_next[write_block] <= available_list[available_head];
                        write_block <= available_list[available_head];
                        if (available_head + 1 < 256) begin
                            available_head <= available_head + 1;
                        end
                        else begin
                            available_head <= 0;
                        end
                        //size减小
                        history_data_size <= history_data_size - 32;
                    end
                end
            end
        end
    end

    always @(posedge clk) begin
        if (rst) begin
            read_state <= 1'b0;
            read_address_counter <= 0;
            history_read_index <= 0;
            totle_read_counter <= 0;
            available_tail <= 255;
            
            //初始化块的地址
            for (i = 0; i < 256; i=i+1) begin
                available_list[i] <= i;          
            end
        end
        else begin
            if (dequeue_en && read_state == 1'b0) begin
                //修改当前读状态
                read_state <= 1'b1;
                read_block <= dequeue_value;
                read_address_counter <= 0;
                history_read_index <= dequeue_value;
                totle_read_counter <= 0;
                dequeue_success <= 1'b1;
            end

            if (read_state==1'b1 && totle_read_counter<=package_size[history_read_index] && read_address_counter<32) begin
                dequeue_success <= 1'b0;
                read_en_out <= 1'b1;
                read_address_out <= block_address[read_block] + read_address_counter;
                read_address_counter <= read_address_counter + 1;
                totle_read_counter <= totle_read_counter + 1;
                //如果读到了一个块的最后一个字，则准备进行下一个块的读取
                if (read_address_counter == 31) begin
                    read_address_counter <= 0;
                    if (block_is_last[read_block]==1'b1) begin
                        //已经是最后一个块，不需要继续了
                        read_state <= 1'b0;
                        //read_en_out <= 1'b0;
                    end
                    else if (block_is_last[read_block]==1'b0) begin
                        //根据next数组读取下一个块的内容
                        read_block <= block_next[read_block];
                        //计数器归零
                        read_address_counter <= 0;
                    end
                    //读取数据结束以后，将读取完毕的块号加入到空闲队列中
                    available_list[available_tail] <= read_block;

                    //空闲队列指针向后移动并取模，实现循环队列的功能
                    if (available_tail + 1 < 256) begin
                        available_tail <= available_tail + 1;
                    end
                    else begin
                        available_tail <= 0;
                    end
                end
            end
        end
    end


    assign manager_read_ready = ~read_state;
endmodule